<template>
  <div class="ep-widget-form-container">
    <el-card shadow="never" :style="cardStyle">
      <el-scrollbar :style="{ height: panelHeight }">
        <el-form
          :model="formModel"
          :style="{ height: panelHeight }"
          :validate-on-rule-change="false"
          :hide-required-asterisk="false"
          :label-position="labelPosition"
          :label-width="labelWidth"
          :size="size"
        >
          <draggable
            class="form-widget-list flex"
            tag="transition-group"
            item-key="id"
            v-bind="dragOptions"
            :component-data="componentData"
            :list="widgetList"
            :move="checkMove"
            @start="dragging = true"
            @end="dragging = false"
            @add="(evt) => onDragAdd(evt, widgetList)"
            @update="onDragUpdate"
          >
            <template #item="{ element: widget, index }">
              <div v-if="widget.type === 'card'" style="width: 100%">
                <component
                  :is="`m-${widget.type}`"
                  v-slot="{ components }"
                  v-model="formModel[widget.options.name]"
                  :form-data="formModel"
                  :widget-list="widgetList"
                  :item="widget"
                  :index="index"
                  :designer="true"
                >
                  <draggable
                    class="form-widget-list flex"
                    tag="transition-group"
                    item-key="id"
                    v-bind="dragOptions"
                    :component-data="componentData"
                    :list="components"
                    :move="checkMove"
                    @start="dragging = true"
                    @end="dragging = false"
                    @add="(evt) => onDragAdd(evt, components)"
                    @update="onDragUpdate"
                  >
                    <template #item="{ element: colWidget, index: colIndex }">
                      <div style="width: 100%">
                        <component
                          :is="`m-${colWidget.type}`"
                          v-model="formModel[colWidget.options.name]"
                          :form-data="formModel"
                          :widget-list="components"
                          :item="colWidget"
                          :index="colIndex"
                          :designer="true"
                        />
                      </div>
                    </template>
                  </draggable>
                </component>
              </div>
              <div v-else style="width: 100%">
                <component
                  :is="`m-${widget.type}`"
                  v-model="formModel[widget.options.name]"
                  :form-data="formModel"
                  :widget-list="widgetList"
                  :item="widget"
                  :index="index"
                  :designer="true"
                />
              </div>
            </template>
          </draggable>
        </el-form>
        <div v-if="widgetList.length === 0" class="form-empty">从左侧拖拽或点击来添加字段</div>
      </el-scrollbar>
    </el-card>
  </div>
</template>

<script>
import { ref, reactive, toRefs, computed, inject } from 'vue'
import draggable from '@marshallswain/vuedraggable'
import fields from './field/index'

export default {
  components: { draggable, ...fields },
  props: {
    /** 平台类型 PC/Pad/H5 */
    layoutType: {
      type: String,
      required: true
    },
    /** 容器滚动条高度 */
    height: {
      type: Number,
      default: 0
    },
    /** 组件列表 */
    widgetList: {
      type: Array,
      default: null
    },
    /** 表单配置 */
    formConfig: {
      type: Object,
      default: null
    }
  },
  setup(props) {
    const panelHeight = computed(() => {
      return props.height + 'px'
    })

    const cardStyle = computed(() => {
      if (props.layoutType === 'Pad') {
        return { maxWidth: '820px', borderRadius: '20px' }
      }
      if (props.layoutType === 'H5') {
        return { maxWidth: '390px', borderRadius: '20px' }
      }
      return {}
    })

    const labelWidth = computed(() => (props.formConfig && props.formConfig.pc?.labelWidth) || 100)
    const size = computed(() => (props.formConfig && props.formConfig.pc?.size) || 'default')
    const labelPosition = computed(() => (props.formConfig && props.formConfig.pc?.labelPosition) || 'left')

    const drag = reactive({
      dragging: false,
      componentData: {
        tag: 'div',
        type: 'transition-group'
      },
      dragOptions: {
        animation: 300,
        group: 'people',
        ghostClass: 'ghost',
        disabled: false,
        handle: '.drag-handler'
      }
    })

    /** 表单数据对象 */
    const formModel = ref({})

    const setSelected = inject('setSelected', null)

    /** 拖拽组件进入表单时触发 */
    const onDragAdd = (evt, widgetList) => {
      const newIndex = evt.newIndex
      if (widgetList[newIndex]) {
        setSelected(widgetList[newIndex])
      }
    }

    /** 拖拽移动组件时触发 */
    const checkMove = () => {
      return true
    }
    /** 拖拽移动组件有变化时触发 */
    const onDragUpdate = () => {
      console.log('onDragUpdate')
    }

    return {
      panelHeight,
      cardStyle,
      labelWidth,
      labelPosition,
      size,
      ...toRefs(drag),
      formModel,
      checkMove,
      onDragAdd,
      onDragUpdate
    }
  }
}
</script>

<style lang="scss">
.ep-widget-form-container {
  height: 100%;

  .form-widget-list {
    height: 100%;
    padding: 3px;

    &.flex {
      display: flex;
      flex-direction: row;
      flex-wrap: wrap;
      align-content: flex-start;
    }
  }

  .form-empty {
    position: absolute;
    text-align: center;
    height: 20px !important;
    min-height: 20px !important;
    font-size: 20px;
    top: 50%;
    width: 100%;
    margin-top: -10px;
    color: #ccc;
  }

  .el-scrollbar {
    :deep(.el-scrollbar__wrap),
    :deep(.el-scrollbar__view) {
      overflow-x: hidden;
    }
  }

  .ghost {
    content: '';
    font-size: 0;
    height: 3px;
    box-sizing: border-box;
    background: #409eff;
    border: 2px solid #409eff;
    outline-width: 0;
    padding: 0;
    overflow: hidden;
    flex: 1;
  }
}
</style>
